# Title: Numeros Primos               		    Filename: primes.s
# Author: Romero Vega Andrea Carolina		    Date: 30 / Marzo / 2017
# Description: primos
# Input: -
# Output: Numeros primos

@@@@@@@@@@@@@
@ registers @
@@@@@@@@@@@@@

@ r1 points to address of "prime"
@ r3 number we are checking 	(N in Knuth)
@ r4 count of primes		(J in Knuth)
@ r5 divisors we are checking	
@ r6 index for the prime divisors
@ r7 will hold remainder	(R in Knuth)
@ r8 will hold quotient		(Q in Knuth)
@ r9 number of primes sought.

.section	.bss
.comm prime, 2000	@ Reserve space for the primes

.section	.data
spc:			@ Space the primes with 3 spaces
	.ascii "  "
len = . - spc
nl: 			@ Just a newline
	.ascii "\n"
limit:			@ Index of last prime we need
	.long 500 

.section .text
.globl	_start
_start:

P1:			@ Setting up
ldr r1, =prime		@ r1 points to "prime"
mov r0, $2		@ First prime is 2
str r0, [r1]		@ Store this number in "prime"
ldr r0, =limit
ldr r9, [r0]		@ r2 holds number of primes to find
mov r3, $3		@ Initialize N to 3
mov r4, $1		@ Initialize J to 1

P2:			@ We come here when we have found a prime
add r4, r4, $1		@ Increment J
str r3, [r1, #4]!	@ Store N in "prime" (with writeback)

P3:
cmp r4, r9		@ Check if we are done
bge P9			@ if so branch to p9

P4:
add r3, r3, $2		@ Add 2 to N 

P5:			@ Start checking divisors
ldr r6, =prime		@ Copy pointer to start of "prime"
ldr r5, [r6]		@ Load first divisor
mov r7, r3		@ Copy N into R
mov r8, $0		@ Initialize Q

P6:
cmp r7, r5		@ if R >= divisor
subge r7, r7, r5 	@ Subtract divisor from R
addge r8, r8, $1	@ Increment Q
bge P6			@ Repeat
cmp r7, $0		@ if R == 0 ...
beq P4			@ N is not prime so try next N

P7:
cmp r8, r5		@ Compare Q with divisor
ble P2			@ if Q <= divisor, N is prime

P8:
mov r7, r3		@ Reset r7 to N
mov r8, $0		@ Reset Q
ldr r5, [r6, #4]!	@ Get next divisor
bal P6			@ Divide again

P9:
mov r0, $1		@ Choose stdout
mov r4, $0		@ Use r4 as a temporary counter
mov r5, $0		@ r5 counts total primes printed
ldr r6, =prime		@ Pointer to "prime"
ldr r3, [r6]		@ Load first prime

printLoop:
bl print_num		@ Function call
add r4, $1		@ Add one to temp counter
add r5, $1		@ Add one to counter
cmp r5, r9 		@ Are we done?
bge exit		@ If so, exit
cmp r4, $9		@ After 10 primes ...
bgt newline		@ Print a newline
ble space		@ Add spaces

space:                  @ We jump here if
mov r0, $1              @ We are going to 
ldr r1, =spc		@ Print spaces
ldr r2, =len	
mov r7, $4
svc $0
ldr r3, [r6, #4]!	@ Load next prime
bal printLoop           @ Continue printing

newline:                @ We jump here if
mov r0, $1              @ We are going to
ldr r1, =nl             @ Print a newline
mov r2, $1
mov r7, $4
svc $0
ldr r3, [r6, #4]!       @ Load next prime
mov r4, $0              @ Reset temporary counter
bal printLoop		@ Continue printing

@@@@@@@@@@@@@@@@@@@@@@
@ print_num function @
@@@@@@@@@@@@@@@@@@@@@@

print_num:
	stmfd sp!, {r0-r9, lr}	@ Push regs to stack
	mov r4, $0 		@ Set division counter to zero
	mov r5, $1		@ Set char counter to one

loop:				@ Division routine
	cmp r3, $9		
	ble stackPush		@ If r3 <= 9, call stackPush
	sub r3, r3, $10		@ Else, subtract 10 from r3
	add r4, r4, $1		@ Add one to div. counter
	bal loop		@ Repeat

stackPush:
	add r5, r5, $1		@ Increment char counter
	orr r0, r3, $0x30	@ Logical OR - add 48 to digit to get ascii code
	stmfd	sp!, {r0}	@ Push onto stack
	cmp r4, $0		@ If the div. counter is zero ...
	beq printChars		@ Call print function
	mov r3, r4		@ Else, load div. count into r3
	mov r4, $0		@ Reset div. counter
	bal loop		@ Back to top of loop

printChars:
	mov r1, sp		@ Use stack pointer to provide ascii code
	mov r0, $1		@ Stdout is file descriptor 1
	mov r2, $1		@ Length to print is 1
	mov r7, $4		@ Write syscall
	svc $0			@ Wake kernel
	subs r5, r5, $1		@ Decrement string counter and set flag
	ble return		@ Return if done
	ldmfd sp!, {r0}		@ Pull next char from from stack 
	bal printChars		@ Get next char
return:
	ldmfd sp!, {r0-r9, pc}	@ Restore registers

exit:
mov r0, $1			@ Print a newline
ldr r1, =nl
mov r2, $1
mov r7, $4
svc $0
mov r7, $1			@ Exit
svc $0                          @ Wake Kernel

.end                            